#include "BlurRender.h"
#include "BlurEffect.h"
#include "Game.h"
#include "DepthEffect.h"
#include "ShadowRender.h"

BlurRender::BlurRender()
{

}

BlurRender::BlurRender(const BlurRender&)
{

}

BlurRender::~BlurRender()
{

}


void BlurRender::Initialize()
{
	mWidth = 512;
	mHeight = 512;

	mCDirect3D = CDirect3D::Instance();
	mDeviceContext = mCDirect3D->GetDeviceContext();
	mDevice = mCDirect3D->GetDevice();

	HRESULT result;

	D3D11_TEXTURE2D_DESC sTexDesc;
	sTexDesc.Width = mWidth;
	sTexDesc.Height = mHeight;
	sTexDesc.MipLevels = 1;
	sTexDesc.ArraySize = 1;
	sTexDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
	sTexDesc.SampleDesc.Count = 1;
	sTexDesc.SampleDesc.Quality = 0;
	sTexDesc.Usage = D3D11_USAGE_DEFAULT;
	sTexDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
	sTexDesc.CPUAccessFlags = 0;
	sTexDesc.MiscFlags = 0;

	mDevice->CreateTexture2D(&sTexDesc,NULL, &mRenderTexture);
	mDevice->CreateTexture2D(&sTexDesc,NULL, &mIntermediateRenderTexture);

	D3D11_RENDER_TARGET_VIEW_DESC renderTargetDesc;
	renderTargetDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
	renderTargetDesc.ViewDimension = D3D11_RTV_DIMENSION::D3D11_RTV_DIMENSION_TEXTURE2D;
	renderTargetDesc.Texture2D.MipSlice = 0;

	result = mDevice->CreateRenderTargetView(mRenderTexture, &renderTargetDesc, &mRenderTargetView);
	result = mDevice->CreateRenderTargetView(mIntermediateRenderTexture, &renderTargetDesc, &mIntermediateRenderTargetView);

	D3D11_SHADER_RESOURCE_VIEW_DESC  shaderResourceViewDesc;
	// Setup the description of the shader resource view.
	shaderResourceViewDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
	shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
	shaderResourceViewDesc.Texture2D.MipLevels = 1;

	result = CDirect3D::Instance()->GetDevice()->CreateShaderResourceView(mRenderTexture,&shaderResourceViewDesc,&mRenderTextureResource);
	result = CDirect3D::Instance()->GetDevice()->CreateShaderResourceView(mIntermediateRenderTexture,&shaderResourceViewDesc,&mIntermediateRenderTextureResource);

	mCDirect3D->CreateDepthBuffer(mWidth, mHeight, &mTextureDepthBuffer, &mStencilView);

	mViewport.Width = (float)mWidth;
	mViewport.Height = (float)mHeight;
	mViewport.MinDepth = 0.0f;
	mViewport.MaxDepth = 1.0f;
	mViewport.TopLeftX = 0.0f;
	mViewport.TopLeftY = 0.0f;

	mVerticalBlurEffect = new BlurEffect();
	mVerticalBlurEffect->Initialize(VerticalBlur);

	mHorizontalBlurEffect = new BlurEffect();
	mHorizontalBlurEffect->Initialize(HorizontalBlur);

	InitializeBuffers();

	XMStoreFloat4x4(&mWorldMatrix, XMMatrixIdentity());

	XMVECTOR vectorTarget = XMLoadFloat3(&XMFLOAT3(0,0,0));
	XMVECTOR vectorPosition = XMLoadFloat3(&XMFLOAT3(0,0,-3));
	XMVECTOR vectorUp = XMLoadFloat3(&XMFLOAT3(0,1,0));
	XMStoreFloat4x4(&mViewMatrix, XMMatrixLookAtLH(vectorPosition, vectorTarget, vectorUp));

	XMStoreFloat4x4(&mProjectionMatrix, XMMatrixOrthographicLH(mWidth, mHeight, 1, 10));
}

void BlurRender::InitializeBuffers()
{
	D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
	D3D11_SUBRESOURCE_DATA vertexData, indexData;

	float left, right, top, bottom;
	left = (float)((mWidth / 2) * -1);
	right = left + (float)mWidth;
	top = (float)(mHeight / 2);
	bottom = top - (float)mHeight;

	mIndexCount = 6;

	VertexType* vertices;
	vertices = new VertexType[mIndexCount];
	unsigned long* indices;
	indices = new unsigned long[mIndexCount];

	vertices[0].position = XMFLOAT3(left, top, 0.0f);  // Top left.
	vertices[0].texture = XMFLOAT2(0.0f, 0.0f);

	vertices[1].position = XMFLOAT3(right, bottom, 0.0f);  // Bottom right.
	vertices[1].texture = XMFLOAT2(1.0f, 1.0f);

	vertices[2].position = XMFLOAT3(left, bottom, 0.0f);  // Bottom left.
	vertices[2].texture = XMFLOAT2(0.0f, 1.0f);

	// Second triangle.
	vertices[3].position = XMFLOAT3(left, top, 0.0f);  // Top left.
	vertices[3].texture = XMFLOAT2(0.0f, 0.0f);

	vertices[4].position = XMFLOAT3(right, top, 0.0f);  // Top right.
	vertices[4].texture = XMFLOAT2(1.0f, 0.0f);

	vertices[5].position = XMFLOAT3(right, bottom, 0.0f);  // Bottom right.
	vertices[5].texture = XMFLOAT2(1.0f, 1.0f);

	for(int i=0; i<mIndexCount; i++)
	{
		indices[i] = i;
	}

	vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexBufferDesc.ByteWidth = sizeof(VertexType) * mIndexCount;
	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
	vertexBufferDesc.CPUAccessFlags = 0;
	vertexBufferDesc.MiscFlags = 0;
	vertexData.pSysMem = vertices;
	HRESULT result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexData, &mVertexBuffer);


	indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	indexBufferDesc.ByteWidth = sizeof(unsigned long) * mIndexCount;
	indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
	indexBufferDesc.CPUAccessFlags = 0;
	indexBufferDesc.MiscFlags = 0;

	// Give the subresource structure a pointer to the index data.
	indexData.pSysMem = indices;

	// Create the index buffer.
	result = mDevice->CreateBuffer(&indexBufferDesc, &indexData, &mIndexBuffer);
}

void BlurRender::Update()
{

}

void BlurRender::Render()
{
	float color[4];

	// Setup the color to clear the buffer to.
	color[0] = 1.f;
	color[1] = 0.f;
	color[2] = 1.f;
	color[3] = 1.f;

	mDeviceContext->OMSetRenderTargets(1, &mIntermediateRenderTargetView, mStencilView);
	mDeviceContext->RSSetViewports(1, &mViewport);
	mDeviceContext->ClearRenderTargetView(mIntermediateRenderTargetView, color);
	mDeviceContext->ClearDepthStencilView(mStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

	unsigned int stride = sizeof(VertexType); 
	unsigned int offset = 0;

	mDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	mDeviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset);
	mDeviceContext->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R32_UINT, 0);
	

	mHorizontalBlurEffect->SetTextureToBlur(mTextureToBlur);
	mHorizontalBlurEffect->SetViewWidth(512);
	mHorizontalBlurEffect->SetTransformsMatrices(mWorldMatrix, mViewMatrix, mProjectionMatrix);
	mHorizontalBlurEffect->Render(6);

	//Vertical

	mDeviceContext->OMSetRenderTargets(1, &mRenderTargetView, mStencilView);
	mDeviceContext->RSSetViewports(1, &mViewport);
	mDeviceContext->ClearRenderTargetView(mRenderTargetView, color);
	mDeviceContext->ClearDepthStencilView(mStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);

	mDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	mDeviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset);
	mDeviceContext->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R32_UINT, 0);

	mVerticalBlurEffect->SetTextureToBlur(mIntermediateRenderTextureResource);
	mVerticalBlurEffect->SetViewWidth(512);
	mVerticalBlurEffect->SetTransformsMatrices(mWorldMatrix, mViewMatrix, mProjectionMatrix);
	mVerticalBlurEffect->Render(6);
}

ID3D11ShaderResourceView* BlurRender::GetRenderTexture()
{
	return mRenderTextureResource;
}

void BlurRender::SetTextureToBlur(ID3D11ShaderResourceView* pTexture)
{
	mTextureToBlur = pTexture;
}
